{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Change Detection with Instance Segmentation\n",
    "\n",
    "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/opengeos/geoai/blob/main/docs/examples/change_detection.ipynb)\n",
    "\n",
    "This notebook demonstrates the change detection functionality in GeoAI, which provides instance segmentation and confidence scoring for individual change objects. \n",
    "\n",
    "The change detection functionality builds upon the [torchange](https://github.com/Z-Zheng/pytorch-change-models) package developed by Dr. Zhuo Zheng. We have made it much easier to analyze remote sensing imagery and visualize the results.\n",
    "\n",
    "## Overview\n",
    "\n",
    "The change detection system provides:\n",
    "\n",
    "- **Instance Segmentation**: Each change object gets a unique ID\n",
    "- **Confidence Scores**: Individual confidence values for each detected instance\n",
    "- **Proper GeoTIFF Output**: Maintains spatial reference information\n",
    "\n",
    "## Key Features\n",
    "\n",
    "- Instance-level change detection with unique IDs\n",
    "- Confidence scoring for quality assessment\n",
    "- Support for large GeoTIFF files\n",
    "- Comprehensive analysis capabilities"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Install packages"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# %pip install geoai-py"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Import libraries"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import geoai\n",
    "import os\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from pathlib import Path\n",
    "from geoai.change_detection import ChangeDetection"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Setup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Check if CUDA is available\n",
    "device = geoai.get_device()\n",
    "print(f\"Using device: {device}\")\n",
    "\n",
    "# Set up paths\n",
    "out_folder = \"change_detection_results\"\n",
    "Path(out_folder).mkdir(exist_ok=True)\n",
    "\n",
    "print(f\"Working directory: {out_folder}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Download sample data\n",
    "\n",
    "We'll use NAIP imagery for Las Vegas to demonstrate change detection."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Download NAIP imagery\n",
    "naip_2019_url = \"https://huggingface.co/datasets/giswqs/geospatial/resolve/main/las_vegas_naip_2019_a.tif\"\n",
    "naip_2022_url = \"https://huggingface.co/datasets/giswqs/geospatial/resolve/main/las_vegas_naip_2022_a.tif\"\n",
    "\n",
    "naip_2019_path = geoai.download_file(naip_2019_url)\n",
    "naip_2022_path = geoai.download_file(naip_2022_url)\n",
    "\n",
    "print(f\"Downloaded 2019 NAIP: {naip_2019_path}\")\n",
    "print(f\"Downloaded 2022 NAIP: {naip_2022_path}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Visualize sample data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Check raster information\n",
    "geoai.get_raster_info(naip_2019_path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# View the images\n",
    "geoai.view_raster(naip_2019_path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "geoai.view_raster(naip_2022_path)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Initialize Change Detection\n",
    "\n",
    "Create the change detection system with optimal parameters."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Make sure model directory exists\n",
    "Path(\"~/.cache/torch/hub/checkpoints/\").expanduser().mkdir(parents=True, exist_ok=True)\n",
    "\n",
    "# Initialize change detection\n",
    "detector = ChangeDetection(sam_model_type=\"vit_h\")\n",
    "\n",
    "# Configure parameters (following the torchange example)\n",
    "detector.set_hyperparameters(\n",
    "    change_confidence_threshold=145,\n",
    "    use_normalized_feature=True,\n",
    "    bitemporal_match=True,\n",
    ")\n",
    "\n",
    "detector.set_mask_generator_params(\n",
    "    points_per_side=32,\n",
    "    stability_score_thresh=0.95,\n",
    ")\n",
    "\n",
    "print(\"Change detection system initialized!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Run Change Detection\n",
    "\n",
    "Execute change detection with instance segmentation and confidence scoring."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Run change detection\n",
    "results = detector.detect_changes(\n",
    "    naip_2019_path,\n",
    "    naip_2022_path,\n",
    "    output_path=f\"{out_folder}/binary_mask.tif\",\n",
    "    export_probability=True,\n",
    "    probability_output_path=f\"{out_folder}/probability_mask.tif\",\n",
    "    export_instance_masks=True,\n",
    "    instance_masks_output_path=f\"{out_folder}/instance_masks.tif\",\n",
    "    return_detailed_results=True,\n",
    "    return_results=False,\n",
    ")\n",
    "\n",
    "print(f\"Change detection completed!\")\n",
    "print(f\"Total instances detected: {results['summary']['total_masks']}\")\n",
    "print(f\"Image size: {results['summary']['original_shape']}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Analyze Results\n",
    "\n",
    "Display key statistics and quality metrics."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Display statistics\n",
    "if \"statistics\" in results and results[\"statistics\"]:\n",
    "    print(\"Quality Statistics:\")\n",
    "    for metric, stats in results[\"statistics\"].items():\n",
    "        print(f\"  {metric}: mean={stats['mean']:.3f}, std={stats['std']:.3f}\")\n",
    "\n",
    "# Show top instances\n",
    "if \"masks\" in results and len(results[\"masks\"]) > 0:\n",
    "    print(\"\\nTop 5 detected instances:\")\n",
    "    for i, mask in enumerate(results[\"masks\"][:5]):\n",
    "        print(\n",
    "            f\"  {i+1}. Instance {mask['mask_id']}: \"\n",
    "            f\"IoU={mask['iou_pred']:.3f}, \"\n",
    "            f\"Stability={mask['stability_score']:.3f}, \"\n",
    "            f\"Area={mask['area']} pixels\"\n",
    "        )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Visualizations\n",
    "\n",
    "Use the integrated visualization methods for comprehensive analysis."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# probability visualization\n",
    "detector.visualize_results(\n",
    "    naip_2019_path,\n",
    "    naip_2022_path,\n",
    "    f\"{out_folder}/binary_mask.tif\",\n",
    "    f\"{out_folder}/probability_mask.tif\",\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![](https://github.com/user-attachments/assets/e7c00b50-c456-4653-b8ce-0c9ec8f05b7f)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create split comparison visualization\n",
    "detector.create_split_comparison(\n",
    "    naip_2019_path,\n",
    "    naip_2022_path,\n",
    "    f\"{out_folder}/binary_mask.tif\",\n",
    "    f\"{out_folder}/probability_mask.tif\",\n",
    "    f\"{out_folder}/split_comparison.png\",\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Analyze individual instances\n",
    "instance_stats = detector.analyze_instances(\n",
    "    f\"{out_folder}/instance_masks.tif\",\n",
    "    f\"{out_folder}/instance_masks_scores.tif\",\n",
    "    f\"{out_folder}/instance_analysis.png\",\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![](https://github.com/user-attachments/assets/ea1f8a51-ea14-415a-9733-78b243061dd3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Comprehensive Analysis Report\n",
    "\n",
    "Generate a detailed analysis report combining all metrics."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create comprehensive analysis report\n",
    "detector.create_comprehensive_report(results, f\"{out_folder}/comprehensive_report.png\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![](https://github.com/user-attachments/assets/629caf85-0713-4e04-8023-f4273edbbb4c)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## One-Click Complete Analysis\n",
    "\n",
    "For ultimate simplicity, use the complete analysis method."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Alternative: Run complete analysis in one step\n",
    "# This method does everything - detection, file outputs, and all visualizations\n",
    "complete_results = detector.run_complete_analysis(\n",
    "    naip_2019_path, naip_2022_path, \"complete_analysis_results\"\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Summary\n",
    "\n",
    "This notebook demonstrated the change detection functionality in GeoAI with integrated visualization methods:\n",
    "\n",
    "### Key Features Used:\n",
    "1. **Change Detection**: Instance segmentation with confidence scoring\n",
    "2. **Integrated Visualizations**: Built-in methods for comprehensive analysis\n",
    "3. **Simplified API**: Clean, streamlined interface following geoai patterns\n",
    "4. **Complete Analysis**: One-click method for full analysis workflow\n",
    "\n",
    "### Output Files Generated:\n",
    "- `binary_mask.tif`: Traditional binary change detection\n",
    "- `probability_mask.tif`: Probability-weighted change detection  \n",
    "- `instance_masks.tif`: Instance segmentation with unique IDs\n",
    "- `instance_masks_scores.tif`: Confidence scores for each instance\n",
    "- `enhanced_probability_results.png`: Comprehensive visualization\n",
    "- `split_comparison.png`: Before/after split comparison\n",
    "- `instance_analysis.png`: Individual instance analysis\n",
    "- `comprehensive_report.png`: Complete analysis report\n",
    "\n",
    "### Advantages Over Traditional Methods:\n",
    "1. **Instance-Level Analysis**: Each change object has unique ID and metrics\n",
    "2. **Quality Assessment**: Confidence scores for filtering and ranking\n",
    "3. **Rich Visualizations**: Multiple analysis perspectives in one package\n",
    "4. **Simplified Workflow**: Integrated methods reduce code complexity\n",
    "5. **Flexible Usage**: From simple detection to comprehensive analysis"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "geo",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
